/**
 * 用一句话描述该文件作用
 *
 * @Author pengsamkee
 * create at 2016/11/13 0:21
 */

import com.alibaba.fastjson.JSONObject;
import component.DynamicTableRowData;
import component.FileTreeItem;
import constants.TemplateType;
import cookie.ProjectCookie;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.geometry.Orientation;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.stage.DirectoryChooser;
import javafx.stage.Screen;
import javafx.stage.Stage;
import language.Language;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import poi.ExcelReader;
import util.ProjectUtil;
import window.AboutWindow;
import window.ExportWindow;
import window.TemplateSettingWindow;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class Main extends Application {

    private static final Logger logger = LoggerFactory.getLogger(Main.class);

    private static final ImageView folderRootImageView = new ImageView(new Image(ClassLoader.getSystemResourceAsStream("folder-root.png")));

    private final TableView tableView = new TableView();

    private final SplitPane splitPane = new SplitPane();

    private TreeItem<String> fileTreeRootItem = new TreeItem<>("Local Data Tables", folderRootImageView);

    private final TreeView<String> fileTreeView = new TreeView<>(fileTreeRootItem);

    private static final String encoding = "UTF-8";

    private final String[] handleFileExtensions = {"xlsx", "xls"};

    private String configDirectoryPath;

    private ProjectCookie projectCookie;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) {

        Scene scene = new Scene(new VBox(), 1366, 768);

        logger.info("========================================");
        logger.info("==========application start=============");
        logger.info("========================================");

        final DirectoryChooser directoryChooser = new DirectoryChooser();
        this.projectCookie = ProjectCookie.getProjectCookie();

        Language.updateLocale(this.projectCookie.getLanguage(), true);

        MenuBar menuBar = new MenuBar();

        Menu menuFile = new Menu(Language.getTranslation("menu.file"));
        MenuItem openItem = new MenuItem(Language.getTranslation("menu.open"), new ImageView(new Image("menu-open.png")));
        MenuItem clientSettingItem = new MenuItem(Language.getTranslation("menu.client.template.setting"), new ImageView(new Image("menu-setting.png")));
        MenuItem serverSettingItem = new MenuItem(Language.getTranslation("menu.server.template.setting"), new ImageView(new Image("menu-setting.png")));
        MenuItem exportItem = new MenuItem(Language.getTranslation("menu.export"), new ImageView(new Image("menu-save.png")));
        MenuItem exitItem = new MenuItem(Language.getTranslation("menu.close"));
        menuFile.getItems().addAll(openItem, new SeparatorMenuItem(), clientSettingItem, serverSettingItem, new SeparatorMenuItem(), exportItem, new SeparatorMenuItem(), exitItem);
        menuBar.getMenus().addAll(menuFile);

        Menu menuEdit = new Menu(Language.getTranslation("menu.help"));

        Menu languageMenu = new Menu(Language.getTranslation("select.language"));
        final ToggleGroup languageGroup = new ToggleGroup();
        String[] languageNames = Language.getTranslations("languageNames");
        String[] languageKeys = Language.getTranslations("languageKeys");
        int languageIndex = 0;
        for (String languageName : languageNames) {
            RadioMenuItem languageMenuItem = new RadioMenuItem(languageName);
            languageMenuItem.setUserData(languageKeys[languageIndex]);
            languageMenuItem.setToggleGroup(languageGroup);
            languageMenuItem.setSelected(projectCookie.getLanguage().equals(languageKeys[languageIndex]));
            languageMenu.getItems().add(languageMenuItem);
            languageIndex++;
        }

        final MenuItem aboutItem = new MenuItem(Language.getTranslation("menu.about"));
        aboutItem.setOnAction(event -> {
            AboutWindow aboutWindow = new AboutWindow();
            aboutWindow.init(stage);
        });

        menuEdit.getItems().addAll(languageMenu, aboutItem);
        menuBar.getMenus().addAll(menuEdit);

        exportItem.setDisable(true);

        tableView.setVisible(false);

        openItem.setOnAction((ActionEvent t) -> {
            directoryChooser.setInitialDirectory(ProjectUtil.getExportDirectory(this.projectCookie.getConfigDirectoryPath()));
            directoryChooser.setTitle(Language.getTranslation("please.select.config.directory"));//请选择配置根目录...
            File directoryFile = directoryChooser.showDialog(stage);
            if (directoryFile != null) {
                configDirectoryPath = directoryFile.getAbsolutePath();
                if (!configDirectoryPath.equals(this.projectCookie.getConfigDirectoryPath())) {
                    this.projectCookie.setConfigDirectoryPath(configDirectoryPath);
                    try {
                        FileUtils.writeStringToFile(ProjectUtil.getCookieFile("ProjectCookie.json"), JSONObject.toJSONString(this.projectCookie), encoding);
                    } catch (IOException e) {
                        logger.error(e.getMessage());
                        e.printStackTrace();
                    }
                }
                exportItem.setDisable(false);
                fileTreeView.setRoot(null);
                fileTreeRootItem = null;
                buildFileTree(ProjectUtil.getExportDirectory(this.projectCookie.getConfigDirectoryPath()));
                tableView.setVisible(false);
                tableView.getColumns().clear();
            }
        });

        clientSettingItem.setOnAction(event -> {
            TemplateSettingWindow templateSettingWindow = new TemplateSettingWindow();
            templateSettingWindow.init(stage, TemplateType.CLIENT);
        });

        serverSettingItem.setOnAction(event -> {
            TemplateSettingWindow templateSettingWindow = new TemplateSettingWindow();
            templateSettingWindow.init(stage, TemplateType.SERVER);
        });

        exportItem.setOnAction(event -> {
            ExportWindow exportWindow = new ExportWindow();
            exportWindow.init(stage);
        });

        exitItem.setOnAction(event -> {
            Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
            alert.initOwner(stage);
            alert.setTitle(Language.getTranslation("close.tips"));//关闭提示
            alert.setHeaderText(null);
            alert.setContentText(Language.getTranslation("app.close.tips"));//是否关闭基础数据处理工具？
            Optional<ButtonType> result = alert.showAndWait();
            if (result.get() == ButtonType.OK) {
                System.exit(0);
            } else {
            }
        });

        stage.setTitle(Language.getTranslation("app.title"));
        stage.getIcons().add(new Image("app.logo.png"));
        stage.setMaximized(false);
        stage.setResizable(false);

        ScrollPane scrollPane = new ScrollPane();
        scrollPane.setContent(tableView);
        scrollPane.setStyle("-fx-focus-color: transparent;");
        tableView.setMinWidth(1161);
        tableView.setPrefHeight(747);
        fileTreeView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue instanceof FileTreeItem) {
                FileTreeItem fileTreeItem = (FileTreeItem) newValue;
                if (fileTreeItem.isLeaf()) {
                    File file = fileTreeItem.getFile();
                    if (file.isHidden()) {
                        return;
                    }
                    File excelDirectory = new File(this.projectCookie.getConfigDirectoryPath());
                    ExcelReader reader = new ExcelReader(file, excelDirectory.getPath());
                    if (tableView.getColumns().size() != 0) {
                        tableView.getColumns().clear();
                        tableView.scrollTo(0);
                    } else {
                        tableView.setVisible(true);
                    }
                    if (reader.listDatas.size() == 0){
                        return;
                    }
                    List<String> list = reader.listDatas.get(0).get(0);
                    List<String> clientColumnHeaderList = reader.listDatas.get(0).get(1);
                    List<String> serverColumnHeaderList = reader.listDatas.get(0).get(2);
                    DynamicTableRowData dynamicTableRowData = new DynamicTableRowData(list);
                    ObservableList<DynamicTableRowData> tableData = FXCollections.observableArrayList();
                    tableData.addAll(reader.columnData.stream().map(rowData -> dynamicTableRowData.addRow(rowData.toArray(new String[rowData.size()]))).collect(Collectors.toList()));
                    TableColumn tableColumn;
                    TableColumn clientTableColumn;
                    TableColumn serverTableColumn;
                    int index = 0;
                    for (String header : list) {
                        tableColumn = new TableColumn(header);
                        tableColumn.setSortable(false);
                        tableColumn.setPrefWidth(index == 0 ? 60 : 140);
                        tableColumn.setResizable(false);
                        tableColumn.setId(dynamicTableRowData.getColId(index));
                        tableColumn.setStyle("-fx-alignment:CENTER");
                        tableColumn.setCellValueFactory(dynamicTableRowData.getMapCellValueFactory());
                        tableView.getColumns().add(tableColumn);
                        tableView.setManaged(false);
                        clientTableColumn = new TableColumn(clientColumnHeaderList.get(index));
                        clientTableColumn.setSortable(false);
                        clientTableColumn.setPrefWidth(index == 0 ? 60 : 140);
                        clientTableColumn.setResizable(false);
                        clientTableColumn.setId(dynamicTableRowData.getColId(index));
                        clientTableColumn.setStyle("-fx-alignment:CENTER");
                        clientTableColumn.setCellValueFactory(dynamicTableRowData.getMapCellValueFactory());
                        tableColumn.getColumns().add(clientTableColumn);
                        serverTableColumn = new TableColumn(serverColumnHeaderList.get(index));
                        serverTableColumn.setSortable(false);
                        serverTableColumn.setPrefWidth(index == 0 ? 60 : 140);
                        serverTableColumn.setResizable(false);
                        serverTableColumn.setId(dynamicTableRowData.getColId(index));
                        serverTableColumn.setStyle("-fx-alignment:CENTER");
                        serverTableColumn.setCellValueFactory(dynamicTableRowData.getMapCellValueFactory());
                        clientTableColumn.getColumns().add(serverTableColumn);
                        index++;
                    }
                    tableView.setItems(tableData);
                }
            }
        });

        splitPane.setOrientation(Orientation.HORIZONTAL);
        splitPane.getItems().addAll(fileTreeView, scrollPane);
        splitPane.setDividerPosition(0, 0.15);
        splitPane.setPrefHeight(scene.getHeight() - menuBar.getHeight());

        AnchorPane.setTopAnchor(splitPane, 0d);
        AnchorPane.setBottomAnchor(splitPane, 0d);
        AnchorPane.setLeftAnchor(splitPane, 0d);
        AnchorPane.setRightAnchor(splitPane, 0d);

        stage.setScene(scene);
        ((VBox) scene.getRoot()).getChildren().addAll(menuBar, splitPane);

        languageGroup.selectedToggleProperty().addListener(event -> {
            if (languageGroup.getSelectedToggle() != null) {
                this.projectCookie.setLanguage((String) languageGroup.getSelectedToggle().getUserData());
                this.rewriteProjectCookie();
                Language.updateLocale(this.projectCookie.getLanguage(), true);
                menuFile.setText(Language.getTranslation("menu.file"));
                openItem.setText(Language.getTranslation("menu.open"));
                clientSettingItem.setText(Language.getTranslation("menu.client.template.setting"));
                serverSettingItem.setText(Language.getTranslation("menu.server.template.setting"));
                exportItem.setText(Language.getTranslation("menu.export"));
                exitItem.setText(Language.getTranslation("menu.close"));
                menuEdit.setText(Language.getTranslation("menu.help"));
                languageMenu.setText(Language.getTranslation("select.language"));
                aboutItem.setText(Language.getTranslation("menu.about"));
                directoryChooser.setTitle(Language.getTranslation("please.select.config.directory"));//请选择配置根目录...
                stage.setTitle(Language.getTranslation("app.title"));
            } else {
            }
        });

        Rectangle2D primScreenBounds = Screen.getPrimary().getVisualBounds();
        stage.setX((primScreenBounds.getWidth() - stage.getWidth()) / 2);
        stage.setY((primScreenBounds.getHeight() - stage.getHeight()) / 2);

        stage.show();
    }

    public void buildFileTree(File file) {
        fileTreeRootItem = new TreeItem<>("Local Data Tables", folderRootImageView);
        fileTreeView.setRoot(fileTreeRootItem);
        fileTreeRootItem.setExpanded(true);
        File[] files = file.listFiles();
        ProjectUtil.sortFiles(files);
        for (File f : files) {
            if (!f.isHidden() && ProjectUtil.isExtensionFile(f, handleFileExtensions)) {
                TreeItem<String> fileTreeItem = new FileTreeItem(f);
                fileTreeRootItem.getChildren().add(fileTreeItem);
            }
        }
    }

    private void rewriteProjectCookie() {
        try {
            FileUtils.writeStringToFile(ProjectUtil.getCookieFile("ProjectCookie.json"), JSONObject.toJSONString(this.projectCookie), encoding);
        } catch (IOException e) {
            logger.error(e.getMessage());
            e.printStackTrace();
        }
    }

}
